<?php

class system extends Module {
	
	public function __construct () {
		parent::__construct (__CLASS__);
	}
	
	public function __default () {
		redirect (HTTP_HOST . '/admin/cp');
	}
	
	public function regedit () {
		$key = getRequest ('key');
		
		if ($key && getRequest ('value', 'bool')) {
			Regedit::getInstance()->set ($key, getRequest('value'));
			redirect (HTTP_HOST . '/admin/system/regedit?ok');
		}
		
		$response = new ModuleResponse;
		$response->setTemplate ('system/regedit');
		$response->setAttribute ('key', $key);
		
		if (getRequest ('ok', 'bool')) {
			$response->addObject (new SystemMessage (lang('regedit_saved','system')));
		}
		
		if ($key) {
			$value = Regedit::getInstance()->get ($key);
			$response->addObject (new Array2XML ('regedit', array ((string) $value)));
		}
		
		$response->addObject (new Array2XML ('helpers', Regedit::getInstance()->getHelpers()));		
		
		$this->setPageTitle (lang ('admin_header_regedit','system'));
		
		return $response;
	}

	
	public function update () {
		$this->setPageTitle (lang ('admin_header_update','system'));
		
		if (!getRequest ('start', 'bool')) {
			$response = new ModuleResponse;
			$response->setTemplate ('system/update');
			
			if (getRequest ('successfull', 'bool')) {
				$response->addObject (new SystemMessage ('Successfully updated'));
			}
			
			$regedit = Regedit::getInstance ();
	
			$response->addObject (new Array2XML ('system', array (
				'version' => $regedit->get ('//cms/version'),
				'build' => $regedit->get ('//cms/build'),
				'update' => formatDate((int) $regedit->get ('//cms/last_update'))
			)));
			
			return $response;
		}
		
		
		include ENGINE_ROOT . '/libs/pclzip.lib.php';
		
		$oTypeFileRevision = TypesController::getInstance()->getTypeByName ('file_revision');
		$objectsController = ObjectsController::getInstance ();		
		$regedit = Regedit::getInstance ();
		
		$response = new ModuleResponse;
		$response->setTemplate ('system/admin_update');
		
		$currentBuild = (int) $regedit->get ('//cms/build');
		$version = $regedit->get ('//cms/version');

		$response->addObject (new Array2XML ('system', array (
			'version' => $version,
			'build' => $currentBuild,
			'update' => formatDate((int) $regedit->get ('//cms/last_update'))
		)));
		
		if (empty ($_FILES['zip']['tmp_name'])) {
			$response->addObject (new SystemError ('Zip archive with update not uploaded'));
			return $response;
		}
		
		$zipFilePath = DOC_ROOT . '/explay/temp/update.zip';
		
		if (!move_uploaded_file ($_FILES['zip']['tmp_name'], $zipFilePath)) {
			$response->addObject (new SystemError ('Uploading error'));
			return $response;
		}
		
		$zip = new PclZip ($zipFilePath);
		
		try {			
			$listContent = $zip->extract (PCLZIP_OPT_BY_NAME, 'update', PCLZIP_OPT_EXTRACT_AS_STRING);
			
			if (!count ($listContent)) {
				throw new BlockException ('File with update info not found');
			}
			
			$aUpdateInfo = unserialize ($listContent[0]['content']);
			
			if ((int) $aUpdateInfo['for_build'] != $currentBuild) {
				throw new BlockException ('You upload update for other build');
			}
			
			$newBuild = (int) $aUpdateInfo['build'];
			$version = $aUpdateInfo['version'];
			
			$this->unpack ($zip, $currentBuild);
			
			$listContent = $zip->extract (PCLZIP_OPT_BY_NAME, 'mysql', PCLZIP_OPT_EXTRACT_AS_STRING);
			
			if (count ($listContent)) {
				$mysqlDump = str_replace ("\r", '', $listContent[0]['content']);
				$aQueries = explode ("\n", $mysqlDump);
				
				$db = DBController::getInstance ();
				foreach ($aQueries as $query) {
					try {
						$db->query ($query);
					}
					catch (MySQLException $e) {
						continue;
					}
				}
			}
			
			$listContent = $zip->extract (PCLZIP_OPT_BY_NAME, 'php', PCLZIP_OPT_EXTRACT_AS_STRING);
			
			if (count ($listContent)) {
				$php = trim ($listContent[0]['content']);
				$php = rtrim ($php, '?>');
				
				if (substr ($php, 0, 5) == '<?php') {
					$php = substr ($php, 5);
				}
				if (substr ($php, 0, 2) == '<?') {
					$php = substr ($php, 2);
				}

				eval ($php);
			}
			
		} catch (BlockException $e) {
			$response->addObject (new SystemError ($e->getMessage ()));
			return $response;
		}
		
		$sel = new Selection;
		$sel->addType ($oTypeFileRevision);
		$sel->addFilter ('build', $currentBuild-1);
		$res = $sel->getList ();
		
		foreach ($res as $row) {
			$objectsController->getObject($oTypeFileRevision, $row[0])->delete ();
		}
		
		$regedit->set ('//cms/last_build', $currentBuild);
		$regedit->set ('//cms/build', $newBuild);
		$regedit->set ('//cms/last_update', time ());
		$regedit->set ('//cms/version', $version);
		
		if (file_exists ($zipFilePath)) {
			unlink ($zipFilePath);
		}
		
		redirect (HTTP_HOST . '/admin/system/update?successfull');
	}
	
	public function types () {
		$response = $this->getTypes ();
		$response->setTemplate ('system/types');
		
		if (getRequest ('created','bool')) {
			$response->addObject (new SystemMessage (lang('admin_type_created',__CLASS__)));
		}
		if (getRequest ('saved','bool')) {
			$response->addObject (new SystemMessage (lang('admin_type_saved',__CLASS__)));
		}
		
		return $response;
	}
	
	public function add_type () {
		return $this->formType ();
	}
	
	public function edit_type () {
		return $this->formType (getRequest ('param0','int'));
	}
	
	public function fields () {
		if (getRequest ('save_position','bool')) {
			$this->savePosition ();
		}
		
		$typeId = getRequest ('param0','int');
		
		if (!$oType = TypesController::getInstance()->getTypeById ($typeId)) {
			throw new NotFound;
		}
		
		$response = $this->getTypeFields ($typeId);
		$response->setTemplate ('system/fields');
		
		if (getRequest ('created','bool')) {
			$response->addObject (new SystemMessage (lang('admin_field_created',__CLASS__)));
		}
		if (getRequest ('saved','bool')) {
			$response->addObject (new SystemMessage (lang('admin_field_saved',__CLASS__)));
		}
		if (getRequest ('deleted','bool')) {
			$response->addObject (new SystemMessage (lang('admin_field_deleted',__CLASS__)));
		}
		
		return $response;
	}
	
	public function add_field () {
		return $this->fieldForm ();
	}
	
	public function edit_field () {
		return $this->fieldForm (getRequest ('param0'));
	}
	
	public function delete_field () {
		$this->expectSecureGET ();
		
		if (!$oField = ObjectsController::getInstance()->getObject (TypesController::getInstance()->getTypeByName ('explay_field'), getRequest('param0','int'))) {
			throw new NotFound;
		}
		
		$typeId = $oField->getValue ('type_id');
		
		FieldsController::getInstance()->deleteField ($oField);
		$oField->delete ();
		
		redirect (HTTP_HOST . '/admin/system/fields/' . $typeId . '?deleted');
	}
	
	public function guides () {
		$response = $this->getGuides ();
		$response->setTemplate ('system/guides');
		
		if (getRequest ('created','bool')) {
			$response->addObject (new SystemMessage (lang('admin_guide_created',__CLASS__)));
		}
		if (getRequest ('saved','bool')) {
			$response->addObject (new SystemMessage (lang('admin_guide_saved',__CLASS__)));
		}
		if (getRequest ('deleted','bool')) {
			$response->addObject (new SystemMessage (lang('admin_guide_deleted',__CLASS__)));
		}
		
		return $response;
	}
	
	public function add_guide () {
		return $this->formGuide ();
	}
	
	public function edit_guide () {
		return $this->formGuide (getRequest ('param0','int'));
	}
	
	public function delete_guide () {
		$this->expectSecureGET ();
		
		$oTypeGuide = TypesController::getInstance()->getTypeByName ('explay_guide');
		
		if (!$oGuide = ObjectsController::getInstance()->getObject ($oTypeGuide, getRequest ('param0','int'))) {
			throw new NotFound;
		}
		
		$oGuide->delete ();
		redirect (HTTP_HOST . '/admin/system/guides?deleted');
	}
	
	public function images_profiles () {
		$oResponse = $this->getImagesProfiles ();
		$oResponse->setTemplate ('system/imagesProfiles');
		
		if (getRequest ('created','bool')) {
			$oResponse->addObject (new SystemMessage (lang('admin_image_created',__CLASS__)));
		}
		if (getRequest ('saved','bool')) {
			$oResponse->addObject (new SystemMessage (lang('admin_image_saved',__CLASS__)));
		}
		if (getRequest ('deleted','bool')) {
			$oResponse->addObject (new SystemMessage (lang('admin_image_deleted',__CLASS__)));
		}
		
		return $oResponse;
	}
	
	public function add_images_profile () {
		return $this->imageProfileForm ();
	}
	
	public function edit_images_profile () {
		return $this->imageProfileForm (getRequest ('param0','int'));
	}
	
	public function delete_images_profile () {
		$this->expectSecureGET ();
		
		if (!$object = ObjectsController::getInstance()->getObject (TypesController::getInstance()->getTypeByName ('image_profile'), getRequest('param0','int'))) {
			throw new NotFound;
		}
		
		$object->delete ();
		
		redirect (HTTP_HOST . '/admin/system/images_profiles?deleted');
	}
	
	public function types_connections () {
		$response = $this->getTypesConnections ();
		$response->setTemplate ('system/typesConnections');
		
		return $response;
	}
	
	private function imageProfileForm ($id = 'new') {
		$oTypeProf = TypesController::getInstance()->getTypeByName ('image_profile');
		
		if ($id != 'new') {
			if (!$object = ObjectsController::getInstance()->getObject ($oTypeProf, $id)) {
				throw new NotFound;
			}
		}
		
		$form = new Form ($oTypeProf, $id);
		$form->buildFromType ();
		
		$aErrors = array ();
		$aValues = $id == 'new' ? array () : $object->getValues();
		
		if ((getRequest ('param0') == 'save' && $id == 'new') || getRequest ('param1') == 'save') {
			$aValues = $this->getRequestData ($id, $oTypeProf);
			
			if ($id == 'new') {
				$object = new Object ($oTypeProf);
				$object->setValues ($aValues);
				
				$aErrors = $this->getValidateErrors ($object);
				
				if (!in_array ($object->getValue ('exit_type'), array('jpg','gif','png'))) {
					$aErrors['exit_type'] = lang('error_admin_image_undefined_type',__CLASS__);
				}
				
				if (!count ($aErrors)) {
					$object->createNew ();
					
					redirect (HTTP_HOST . '/admin/system/images_profiles?created');
				}
			} else {
				$object->setValues ($aValues);
							
				$aErrors = $this->getValidateErrors ($object);
				
				if (!in_array ($object->getValue ('exit_type'), array('jpg','gif','png'))) {
					$aErrors['exit_type'] = lang('error_admin_image_undefined_type',__CLASS__);
				}
				
				if (!count ($aErrors)) {
					$object->save ();
					
					redirect (HTTP_HOST . '/admin/system/images_profiles?saved');
				}
			}
		}
		
		$form->setErrors ($aErrors);
		$form->setValues ($aValues);
		
		$response = new ModuleResponse;
		$response->setTemplate ('system/imagesProfileForm');
		$response->addObject ($form);
		
		return $response;
	}
	
	private function fieldForm ($fieldId = 'new') {
		$oTypeField = TypesController::getInstance()->getTypeByName ('explay_field');

		$assocTypes = array (
			'integer' => 'scalar',
			'float' => 'scalar',
			'guide' => 'guide',
			'multiguide' => 'guide',
			'tags' => 'tags',
			'boolean' => 'scalar',
			'header' => 'scalar',
			'text' => 'scalar',
			'email' => 'scalar',
			'date' => 'scalar',
			'birthdate' => 'scalar',
			'latin' => 'scalar',
			'image' => 'image',
			'object_value' => 'connected'
		);
		
		$info = array ('default' => '');
		
		if ($fieldId == 'new') {
			$typeId = getRequest ('param0','int');
			
			if (!$oType = TypesController::getInstance()->getTypeById ($typeId)) {
				throw new NotFound;
			}
			
			$fieldType = getRequest ('type');
			
			if ($fieldType != 'scalar' && $fieldType != 'guide' && $fieldType != 'tags' && $fieldType != 'connected' && $fieldType != 'image') {
				$fieldType = 'scalar';
			}
		} else {
			if (!$oField = ObjectsController::getInstance()->getObject ($oTypeField, $fieldId)) {
				throw new NotFound;
			}
			
			$info = FieldsController::getInstance()->getFieldSqlInfo ($fieldId);
			
			if ($info['default'] === null) {
				$info['default'] = 'NULL';
			}
			
			$typeId = $oField->getValue ('type_id');
			$fieldType = $assocTypes[$oField->getValue('character')];
		}
		
		$aErrors = array ();
		$aValues = $fieldId == 'new' ? array () : $oField->getValues ();
		
		$form = new Form ($oTypeField, $fieldId);
		$form->buildFromType ();
		
		// СОХРАНЕНИЕ
		if (getRequest ('param1') == 'save') {
			$aValues = $this->getRequestData ($fieldId, $oTypeField);
			
			if (isset ($aValues['maxlength']) && $aValues['maxlength'] == '') {
				unset ($aValues['maxlength']);
			}
			if (isset ($aValues['error']) && $aValues['error'] == '') {
				unset ($aValues['error']);
			}
			if (isset ($aValues['help']) && $aValues['help'] == '') {
				unset ($aValues['help']);
			}
			
			$defaultValue = 'NULL';
			
			if (mb_strlen (getRequest ('default_value')) && !getRequest ('default_value_null','bool')) {
				$defaultValue = getRequest ('default_value');
			}
			
			if ($fieldId == 'new') {
				$oField = new Object ($oTypeField);
				$oField->setValues ($aValues);
				$oField->setValue ('type_id', $typeId);
				
				$aErrors = $this->getFieldValidate ($oField);
				
				if (!count ($aErrors)) {
					FieldsController::getInstance()->createField ($oField, $defaultValue);
					$oField->createNew ();
					
					redirect (HTTP_HOST . '/admin/system/fields/' . $typeId . '?created');
				}
			} else {
				if (isset ($aValues['character'])) {
					unset ($aValues['character']);
				}
				
				$oldName = $oField->getValue ('field_name');
				$oldRequired = $oField->getValue ('required');
				
				$oField->setValues ($aValues);
				$oField->setValue ('type_id', $typeId);
				
				$aErrors = $this->getFieldValidate ($oField, $fieldId);
				
				if (!count ($aErrors)) {
					if ($oldName != $oField->getValue ('field_name') || $oldRequired != $oField->getValue ('required') || $info['default'] != $defaultValue) {
						FieldsController::getInstance()->changeField ($oldName, $oField, $defaultValue);
					}
					
					$oField->save ();

					redirect (HTTP_HOST . '/admin/system/fields/' . $typeId . '?saved');
				}
			}
		}
		
		$form->setValues ($aValues);
		$form->setErrors ($aErrors);
		
		$response = new ModuleResponse;
		$response->setTemplate ('system/formField');
		$response->setAttribute ('character-type', $fieldType);
		$response->setAttribute ('type-id', $typeId);
		$response->addObject ($form);
		$response->addObject(new Array2XML ('sql', $info));
		
		return $response;
	}
	
	private function formType ($id = 'new') {
		$oType = TypesController::getInstance()->getTypeByName ('explay_type');
		
		$form = new Form ($oType, $id);
		$form->buildFromType ();
		
		$aValues = array ();
		$aErrors = array ();
		
		if ($id != 'new') {
			if (!$object = ObjectsController::getInstance()->getObject ($oType, $id)) {
				throw new NotFound;
			}
			
			$aValues = $object->getValues ();
		}
		
		if ((getRequest ('param1') == 'save' && $id != 'new') || (getRequest ('param0') == 'save' && $id == 'new')) {
			$aValues = $this->getRequestData ($id, $oType);
			
			if ($id == 'new') {
				$object = new Object ($oType);
				$object->setValues ($aValues);
				$object->setValue ('parend_id', 0);
				$object->setValue ('locked', 0);
				
				$aErrors = $this->getTypeValidate ($object, $id);
				
				if (!count ($aErrors)) {
					TypesController::getInstance()->createNewType ($object);
					$object->createNew ();
					
					redirect (HTTP_HOST . '/admin/system/types?created');
				}
			} else {
				$oldTableName = $object->getValue ('table_name');
				$object->setValues ($aValues);
				
				$aErrors = $this->getTypeValidate ($object, $id);
				
				if (!count ($aErrors)) {
					$tableName = $object->getValue ('table_name');
					
					if ($oldTableName != $tableName) {
						TypesController::getInstance()->renameTypeTable ($oldTableName, $tableName);
					}
					$object->save ();
					
					redirect (HTTP_HOST . '/admin/system/types?saved');
				}
			}
		}
		
		$form->setErrors ($aErrors);
		$form->setValues ($aValues);
		
		$response = new ModuleResponse;
		$response->setTemplate ('system/formType');
		$response->addObject ($form);
		
		return $response;
	}
	
	private function formGuide ($id = 'new') {
		$oType = TypesController::getInstance()->getTypeByName ('explay_guide');
		
		$form = new Form ($oType, $id);
		$form->buildFromType ();
		
		$aValues = array ();
		$aErrors = array ();
		
		if ($id != 'new') {
			if (!$object = ObjectsController::getInstance()->getObject ($oType, $id)) {
				throw new NotFound;
			}
			
			$aValues = $object->getValues ();
		}
		
		if ((getRequest ('param1') == 'save' && $id != 'new') || (getRequest ('param0') == 'save' && $id == 'new')) {
			$aValues = $this->getRequestData ($id, $oType);
			
			if ($id == 'new') {
				$object = new Object ($oType);
				$object->setValues ($aValues);
				
				$aErrors = $this->getGuideValidate ($object);
				
				if (!count ($aErrors)) {
					$object->createNew ();
					
					redirect (HTTP_HOST . '/admin/system/guides?created');
				}
			} else {
				$object->setValues ($aValues);
				
				$aErrors = $this->getGuideValidate ($object, $id);
				
				if (!count ($aErrors)) {
					$tableName = $object->getValue ('table_name');
					
					$object->save ();
					
					redirect (HTTP_HOST . '/admin/system/guides?saved');
				}
			}
		}
		
		$form->setErrors ($aErrors);
		$form->setValues ($aValues);
		
		$response = new ModuleResponse;
		$response->setTemplate ('system/formGuide');
		$response->addObject ($form);
		
		return $response;
	}
	
	public function getImagesProfiles () {
		$oTypeProf = TypesController::getInstance()->getTypeByName ('image_profile');
		
		$sel = new Selection;
		$sel->addType ($oTypeProf);
		$sel->setOrder ('title');
		
		$aObjects = ObjectsController::getInstance()->getObjectsList ($sel->getList ());
		
		$response = new ModuleResponse;
		
		foreach ($aObjects as $object) {
			$response->addObject ($object);
		}
		
		return $response;
	}
	
	public function getGuides () {
		$typesController = TypesController::getInstance ();
		$oTypeGuide = $typesController->getTypeByName ('explay_guide');
		
		$sel = new Selection;
		$sel->addType ($oTypeGuide);
		
		$aObjects = ObjectsController::getInstance()->getObjectsList ($sel->getList ());
		
		$response = new ModuleResponse;
		
		foreach ($aObjects as $object) {
			$object->setAttribute ('guide-type-title', $typesController->getTypeById($object->getValue ('type_id'))->getTitle ());
			$response->addObject ($object);
		}
		
		return $response;
	}
	
	public function getTypes () {
		$oType = TypesController::getInstance()->getTypeByName ('explay_type');
		
		$sel = new Selection;
		$sel->addType ($oType);
		$sel->setOrder ('title');
		
		$aObjects = ObjectsController::getInstance()->getObjectsList ($sel->getList ());
		
		$response = new ModuleResponse;
		
		foreach ($aObjects as $object) {
			$response->addObject ($object);
		}
		
		return $response;
	}
	
	public function getTypesConnections ($filteredTypeId = false) {
		$typesController = TypesController::getInstance ();
		$fieldsController = FieldsController::getInstance ();
		
		$oType = $typesController->getTypeByName ('explay_types_connection');
		
		$sel = new Selection;
		$sel->addType ($oType);
		
		if ($filteredTypeId) {
			$sel->addFilter ('parent_type_id', $filteredTypeId);
			$sel->addFilter ('child_type_id', $filteredTypeId);
			$sel->setLogicOr ();
		}
		
		$sel->setOrder ('parent_type_id');
		
		$aObjects = ObjectsController::getInstance()->getObjectsList ($sel->getList ());
		
		$response = new ModuleResponse;
		
		foreach ($aObjects as $object) {
			$parentTypeTitle = $typesController->getTypeById($object->getValue ('parent_type_id'))->getTitle ();
			$childTypeTitle = $typesController->getTypeById($object->getValue ('child_type_id'))->getTitle ();
			
			$object->setAttribute ('parent-type-title', $parentTypeTitle);
			$object->setAttribute ('child-type-title', $childTypeTitle);
			
			$parentFieldId = $object->getValue ('parent_field_id');
			$parentFieldTitle = 'id';
			if ($parentFieldId) {
				$parentFieldTitle = $fieldsController->getField($parentFieldId)->getTitle ();
			}
			
			$childFieldTitle = $fieldsController->getField($object->getValue ('child_rel_field_id'))->getTitle ();
			
			$object->setAttribute ('parent-field-title', $parentFieldTitle);
			$object->setAttribute ('child-field-title', $childFieldTitle);
			
			$response->addObject ($object);
		}
		
		return $response;
	}
	
	/*public function getTypesConnectedWith ($typeId) {
		$typesController = TypesController::getInstance ();
		
		$oTypeType = $typesController->getTypeByName ('explay_type');
		$oTypeConnection = $typesController->getTypeByName ('explay_types_connection');
		
		$sel = new Selection;
		$sel->addType ($oTypeConnection);
		$sel->addFilter ('parent_type_id', $typeId);
		$sel->addFilter ('child_type_id', $typeId);
		$sel->setLogicOr ();
		
		$res = array ();
		
		$aObjects = ObjectsController::getInstance()->getObjectsList ($sel->getList ());
		
		foreach ($aObjects as $object) {
			
		}
		
		$response = new ModuleResponse;
		
		return $response;
	}*/
	
	public function getTypeFields ($typeId) {
		$oTypeField = TypesController::getInstance()->getTypeByName ('explay_field');
		
		$sel = new Selection;
		$sel->addType ($oTypeField);
		$sel->addFilter ('type_id', $typeId);
		$sel->setOrder ('position');
		
		$aObjects = ObjectsController::getInstance()->getObjectsList ($sel->getList ());
		
		$response = new ModuleResponse;
		$response->setAttribute ('type-id', $typeId);
		
		foreach ($aObjects as $object) {
			$response->addObject ($object);
		}
		
		return $response;
	}
	
	public function getTypeFieldsByOne ($fieldId) {
		if (!$oField = FieldsController::getInstance()->getField ($fieldId)) {
			return new ModuleResponse;
		}
		
		return $this->getTypeFields ($oField->getTypeId ());
	}
	
	public function ajax_get_type_fields () {
		$oTypeField = TypesController::getInstance()->getTypeByName ('explay_field');
		
		$sel = new Selection;
		$sel->addType ($oTypeField);
		$sel->addFilter ('type_id', getRequest ('param0','int'));
		$sel->setOrder ('position');
		
		$aObjects = ObjectsController::getInstance()->getObjectsList ($sel->getList ());
		
		$response = array ();
		
		foreach ($aObjects as $object) {
			$response[]['field'] = array (
				'id' => $object->getId (),
				'title' => $object->getValue ('title')
			);
		}
		
		$this->flush ((string) new Array2XML ('fields', $response), 'text/xml');
	}
	
	public function ajax_type_fields_connection () {
		$typesController = TypesController::getInstance ();
		$objectsController = ObjectsController::getInstance ();
		
		$oTypeConnection = $typesController->getTypeByName ('explay_types_connection');
		$oTypeField = $typesController->getTypeByName ('explay_field');
		
		$connectionId = getRequest ('connection','int');
		$typeId = getRequest ('type','int');
		
		if (!$oConnection = $objectsController->getObject ($oTypeConnection, $connectionId)) {
			$this->flush ((string) new Array2XML ('fields', array ()), 'text/xml');
		}
		
		if ($oConnection->getValue ('parent_type_id') == $typeId) {
			$needTypeId = $oConnection->getValue ('child_type_id');
		} elseif ($oConnection->getValue ('child_type_id') == $typeId) {
			$needTypeId = $oConnection->getValue ('parent_type_id');
		} else {
			$this->flush ((string) new Array2XML ('fields', array ()), 'text/xml');
		}
		
		$sel = new Selection;
		$sel->addType ($oTypeField);
		$sel->addFilter ('type_id', $needTypeId);
		$sel->setOrder ('position');
		
		$aObjects = $objectsController->getObjectsList ($sel->getList ());
		
		$response = array ();
		
		foreach ($aObjects as $object) {
			$response[]['field'] = array (
				'id' => $object->getId (),
				'title' => $object->getValue ('title')
			);
		}
		
		$this->flush ((string) new Array2XML ('fields', $response), 'text/xml');
	}
	
	private function savePosition () {
		if (!isset ($_POST['field']) || !is_array ($_POST['field'])) {
			return;
		}
		
		$oTypeField = TypesController::getInstance()->getTypeByName ('explay_field');
		
		$aValues = $_POST['field'];

		foreach ($aValues as $fieldId => $position) {
			if (is_array ($position)) {
				return;
			}
			
			if ($oField = ObjectsController::getInstance()->getObject ($oTypeField, $fieldId)) {
				$oField->setValue ('position', (int) $position);
				$oField->save ();
			}
		}
	}
	
	private function getGuideValidate (Object $object, $id = false) {
		$aErros = array ();
		
		if (!TypesController::getInstance()->getTypeById ($object->getValue ('type_id'))) {
			$aErrors['type_id'] = lang('error_admin_guide_undefined_type',__CLASS__);
			return $aErrors;
		}
		
		$sel = new Selection;
		$sel->addType ($object->getType ());
		$sel->addFilter ('type_id', $object->getValue ('type_id'));
		if ($id !== false) {
			$sel->addFilter ('id', $id, '!=');
		}
		
		if ($sel->getTotalCount () != 0) {
			$aErrors['type_id'] = lang('error_admin_guide_type_exists',__CLASS__);
			return $aErrors;
		}
		
		if (!$oField = FieldsController::getInstance()->getField ($object->getValue ('label_field_id'))) {
			$aErrors['label_field_id'] = lang('error_admin_guide_incorrect_field',__CLASS__);
			return $aErrors;
		}
		
		if ($oField->getTypeId () != $object->getValue ('type_id')) {
			$aErrors['label_field_id'] = lang('error_admin_guide_incorrect_field',__CLASS__);
		}
		
		return $aErrors;
	}
	
	/**
	 * @param Object $oField
	 * @param integer $id
	 * @return array
	 */
	private function getFieldValidate (Object $oField, $id = false) {
		$aErrors = array ();
		$typeId = 0;
		
		if (TypesController::getInstance()->getTypeById ($oField->getValue ('type_id'))) {
			$typeId = $oField->getValue ('type_id');
		} else {
			$aErrors['type_id'] = lang('error_admin_field_invalid_type',__CLASS__);
		}
		
		if ($oField->getValue ('field_name') == '') {
			$aErrors['field_name'] = lang('error_admin_field_empty_name',__CLASS__);
		}
		
		if (!isset ($aErrors['field_name']) && !preg_match("#^[a-zA-Z0-9_]+$#", $oField->getValue ('field_name'))) {
			$aErrors['field_name'] = lang('error_admin_field_name_latin',__CLASS__);
		}
		
		if (!isset ($aErrors['field_name'])) {
			$sel = new Selection;
			$sel->addType ($oField->getType ());
			$sel->addFilter ('field_name', $oField->getValue ('field_name'));
			$sel->addFilter ('type_id', $typeId);
			if ($id !== false) {
				$sel->addFilter ('id', $id, '!=');
			}
			
			if ($sel->getTotalCount () > 0) {
				$aErrors['field_name'] = lang('error_admin_field_name_already_exists',__CLASS__);
			}
		}
		
		if ($oField->getValue ('title') == '') {
			$aErrors['title'] = lang('error_admin_field_title_empty',__CLASS__);
		}
		
		$character = $oField->getValue ('character');
		
		$aCharacters = array ('integer','float','guide','multiguide','tags','boolean','header','text','email','date','birthdate','latin','image','object_value');
		if (!in_array ($character, $aCharacters)) {
			$aErrors['character'] = lang('error_admin_field_incorrect_character',__CLASS__);
		}
		
		if ($character == 'image') {
			$sel = new Selection;
			$sel->addType (TypesController::getInstance()->getTypeByName ('image_profile'));
			$sel->addFilter ('id', $oField->getValue ('additional_id'));
			
			if ($sel->getTotalCount () == 0) {
				$aErrors['additional_id'] = lang('error_admin_field_image_profile',__CLASS__);
			}
		} elseif ($character == 'guide' || $character == 'multiguide') {
			$sel = new Selection;
			$sel->addType (TypesController::getInstance()->getTypeByName ('explay_guide'));
			$sel->addFilter ('id', $oField->getValue ('additional_id'));
			
			if ($sel->getTotalCount () == 0) {
				$aErrors['additional_id'] = lang('error_admin_field_guide',__CLASS__);
			}
		}  elseif ($character == 'object_value') {
			$sel = new Selection;
			$sel->addType (TypesController::getInstance()->getTypeByName ('explay_field'));
			$sel->addFilter ('id', $oField->getValue ('additional_id'));
			
			if ($sel->getTotalCount () == 0) {
				$aErrors['additional_id'] = lang('error_admin_field_connected_field',__CLASS__);
			}
		}
		
		return $aErrors;
	}
	
	private function getTypeValidate (Object $object, $id) {
		$aErrors = array ();
		
		if ($object->getValue ('name') == '') {
			$aErrors['name'] = lang('error_admin_type_empty_name',__CLASS__);
		}
		
		if (!isset ($aErrors['name'])) {
			$sel = new Selection;
			$sel->addType ($object->getType ());
			$sel->addFilter ('name', $object->getValue ('name'));
			if ($id != 'new') {
				$sel->addFilter ('id', $id, '!=');
			}
			
			if ($sel->getTotalCount () != 0) {
				$aErrors['name'] = lang('error_admin_type_name_already_exists',__CLASS__);
			}
		}
		
		if (!isset ($aErrors['name']) && !preg_match("#^[a-zA-Z0-9_]+$#", $object->getValue ('name'))) {
			$aErrors['name'] = lang('error_admin_type_name_latin',__CLASS__);
		}
		
		if ($object->getValue ('title') == '') {
			$aErrors['title'] = lang('error_admin_type_empty_title',__CLASS__);
		}
		
		if ($object->getValue ('table_name') == '') {
			$aErrors['table_name'] = lang('error_admin_type_empty_table',__CLASS__);
		}
		
		return $aErrors;
	}
	
	private function unpack (PclZip $zip, $currentBuild) {		
		$oTypeFileRevision = TypesController::getInstance()->getTypeByName ('file_revision');
		$objectsController = ObjectsController::getInstance ();
		
		$list = $zip->listContent (); // Получаем список файлов и папок
		
		if (!$list) {
			throw new BlockException ('Zip error: ' . $zip->errorInfo (true));
		}
	
		// Далее смотрим, есть ли такие файлы/папки на сервере
		foreach ($list as $item) {
			if ($item['filename'] == 'update' || $item['filename'] == 'php' || $item['filename'] == 'mysql') {
				continue;
			}
			
			$filename = DOC_ROOT . '/' . trim ($item['filename'], '/');
			
			if ($item['folder']) {
				// Если такой папки нет, то создаем ее
				if (!is_dir ($filename)) {
					mkdir ($filename);
					if (!is_writable ($filename)) {
						chmod ($filename, 0777);
					}
				}
			
			} else {
				if (file_exists ($filename)) { // Если такой файл существует, то переименовываем его и создаем запись в БД
					if (!is_writable ($filename)) {
						chmod ($filename, 0777);
					}
					
					$fileInfo = pathinfo ($filename);
					if (!rename ($filename, $fileInfo['dirname'] . '/' . '#' . $currentBuild . '_' . $fileInfo['filename'] . '.' . $fileInfo['extension'])) {
						throw new BlockException ('Can\'t rename file "' . $filename . '"');
					}
					
					$oRevision = new Object ($oTypeFileRevision);
					$oRevision->setValues (array (
						'filename' => $item['filename'],
						'build' => $currentBuild
					));
					$oRevision->createNew ();
				}
				
				// распаковываем
				$zip->extract (PCLZIP_OPT_BY_NAME, $item['stored_filename']);
			}
		}
	}
	
	/*public function show_connections () {
		$typesController = TypesController::getInstance();
		$fieldsController = FieldsController::getInstance();
		$objectsController = ObjectsController::getInstance();
		
		$oTypeConnection = $typesController->getTypeByName ('explay_types_connection');
		
		$sel = new Selection;
		$sel->addType ($oTypeConnection);
		$sel->setOrder ('parent_type_id');
		
		$res = $sel->getList ();
		
		print "START TRANSACTION;<br>";
		
		foreach ($res as $row) {
			$object = $objectsController->getObject ($oTypeConnection, $row[0]);
			
			$oParentType = $typesController->getTypeById ($object->getValue ('parent_type_id'));
			$oChildType = $typesController->getTypeById ($object->getValue ('child_type_id'));
			$parentFieldName = $object->getValue ('parent_field_id') == 0 ? 'id' : $fieldsController->getField($object->getValue ('parent_field_id'))->getName();
			$childFieldName = $fieldsController->getField($object->getValue ('child_rel_field_id'))->getName();
			
			print "ALTER TABLE `" . $oChildType->getTableName() . "` ADD CONSTRAINT  FOREIGN KEY (`" . $childFieldName . "`) REFERENCES `" . $oParentType->getTableName() . "` (`" . $parentFieldName . "`) ON DELETE CASCADE ON UPDATE CASCADE;<br>";
		}
		
		print "COMMIT;";
		
		exit;
	}*/
}